
package com.pace.gonu.api;

import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.pace.gonu.constants.EndType;
import com.pace.gonu.constants.GameType;
import com.pace.gonu.constants.Order;
import com.pace.gonu.constants.Status;
import com.pace.gonu.model.BoardPath;
import com.pace.gonu.model.PlayRock;
import com.pace.gonu.model.chnl.PlayChannel;
import com.pace.gonu.model.rule.PlayRule;
import com.pace.gonu.model.rule.PlayRuleFactory;
import com.pace.gonu.model.status.PlayStatus;
import com.pace.gonu.play.PlayService;

/**
 * @author pace
 */
@Service
public class UserInputService {
	@Autowired
	private PlayService playService;

	public Order checkEndGame(int chnlnumber) {
		Order orderRed = Order.RED;
		Order orderBlue = Order.BLUE;

		PlayChannel playChannel = playService.getChannel(chnlnumber);
		PlayStatus playStatus = playChannel.getPlayStatusObject();
		PlayRule playRule = PlayRuleFactory.getInstance(playChannel.getGameTypeObject());
		if (playRule.isEndGame(playStatus, orderRed)) {
			return orderBlue;
		}
		
		if (playRule.isEndGame(playStatus, orderBlue)) {
			return orderRed;
		}
		return null;
	}

	public List<BoardPath> getMovePath(String order, int chnlNumber, int rockNumber) {
		PlayChannel playChannel = playService.getChannel(chnlNumber);
		PlayStatus playStatus = playChannel.getPlayStatusObject();
		PlayRock playRock = playStatus.getPlayRocks().get(rockNumber - 1);

		if (!StringUtils.equals(playRock.getOrder().toString(), order)) {
			throw new IllegalStateException("당신의 돌이 아닙니다.");
		}
		PlayRule rule = PlayRuleFactory.getInstance(playChannel.getGameTypeObject());
		return rule.getMovePath(playStatus.getPlayRocks(), playRock);
	}

	public void moveRock(int chnlNumber, int rockNumber, int x, int y, String orderStr) {
		PlayChannel playChannel = playService.getChannel(chnlNumber);
		PlayStatus playStatus = playService.getChannel(chnlNumber).getPlayStatusObject();
		if (!StringUtils.equals(playStatus.getOrder(), orderStr)) {
			throw new IllegalStateException("플레이어로 차례가 아닙니다.");
		}

		if (StringUtils.equals(playService.getChannel(chnlNumber).getPlayStatusObject().getPlayRocks().get(rockNumber - 1).getOrder().toString(), orderStr)) {
			PlayRock moveRock = playService.getChannel(chnlNumber).getPlayStatusObject().getPlayRocks().get(rockNumber - 1);
			moveRock.getPath().setX(x);
			moveRock.getPath().setY(y);

			PlayRule playRule = PlayRuleFactory.getInstance(playChannel.getGameTypeObject());
			
			if (playRule.isCharm(playStatus.getPlayRocks(), moveRock)) {
				playStatus.setStatusType(Status.CHARMINMOVE);
				return;
			}

			changeOrder(orderStr, playChannel);


		} else {
			throw new IllegalStateException("플레이어의 돌은 " + orderStr + " 입니다.");
		}

	}

	public void choiceMoveRock(int chnlNumber, int moveRockNumber, String orderStr) {
		PlayChannel playChannel = playService.getChannel(chnlNumber);
		PlayStatus playStatus = playChannel.getPlayStatusObject();

		validationUserInput(orderStr, playChannel, playStatus);

		PlayRock moveRock = playStatus.getMoveRocks().get(moveRockNumber);
		moveRock.setOrder(Order.valueOf(orderStr));
		playStatus.getPlayRocks().add(moveRock);
		playStatus.getMoveRocks().remove(moveRockNumber);

		PlayRule playRule = PlayRuleFactory.getInstance(playChannel.getGameTypeObject());
		if (playRule.isCharm(playStatus.getPlayRocks(), moveRock)) {
			playStatus.setStatusType(Status.CHARM);
			return;
		}

		if (playRule.isMove(playStatus)) {
			playStatus.setStatusType(Status.MOVE);
			playStatus.getXRocks().clear();
		}

		changeOrder(orderStr, playChannel);

	}

	public void choiceXRock(int chnlNumber, int xRockNumber, String orderStr) {
		PlayChannel playChannel = playService.getChannel(chnlNumber);
		PlayStatus playStatus = playChannel.getPlayStatusObject();

		validationUserInput(orderStr, playChannel, playStatus);

		int removeRockNumber =0;
		for (PlayRock xRock : playStatus.getPlayRocks()) {
			if (removeRockNumber == xRockNumber) {
				playStatus.getXRocks().add(xRock);
				playStatus.getPlayRocks().remove(xRock);
				break;
			}

			removeRockNumber++;
		}

		playStatus.setStatusType(Status.NORMAL);

		PlayRule playRule = PlayRuleFactory.getInstance(playChannel.getGameTypeObject());
		if (playRule.isMove(playStatus)) {
			playStatus.setStatusType(Status.MOVE);
			playStatus.getXRocks().clear();
		}

		changeOrder(orderStr, playChannel);
	}

	public void changeOrder(String orderStr, PlayChannel playChannel) {
		Order order = this.checkEndGame(playChannel.getChnlNumber());
		if (order != null) {
			playService.setEndGame(playChannel.getChnlNumber(), order, EndType.WIN);
		}

		PlayStatus playStatus = playChannel.getPlayStatusObject();
		if (StringUtils.equals(orderStr, Order.RED.toString())) {
			playStatus.setOrder(Order.BLUE);
		} else if (StringUtils.equals(orderStr, Order.BLUE.toString())) {
			playStatus.setOrder(Order.RED);
		} else {
			throw new IllegalStateException("플레이어로 등록되어 있지 않습니다.");
		}
	}

	private void validationUserInput(String orderStr, PlayChannel playChannel, PlayStatus playStatus) {
		if (!GameType.CHARM.equals(playChannel.getGameTypeObject())) {
			throw new IllegalStateException("잘못된 게임타입니다.");
		}

		if (!StringUtils.equals(playStatus.getOrder(), orderStr)) {
			throw new IllegalStateException("플레이어로 차례가 아닙니다.");
		}
	}

}
